package cz.muni.fi.heathtow.web.pages;

import cz.muni.fi.heathrowapi.AircraftService;
import cz.muni.fi.heathrowapi.DestinationService;
import cz.muni.fi.heathrowapi.FlightService;
import cz.muni.fi.heathrowapi.HeathrowRoles;
import cz.muni.fi.heathrowapi.StewardService;
import cz.muni.fi.heathrowapi.dto.FlightDTO;
import cz.muni.fi.heathrowapi.dto.StewardDTO;
import cz.muni.fi.heathtow.web.auth.SecureWicketAuthenticatedWebSession;
import cz.muni.fi.heathtow.web.utils.Utils;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.wicket.Component;
import org.apache.wicket.authroles.authorization.strategies.role.Roles;
import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.AbstractLink;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.list.AbstractItem;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.apache.wicket.util.string.StringValue;

public class FlightsView extends MainPage
{

    private static final long serialVersionUID = 1L;
    public static final String PARAM_DELETE_ID = "delete_id";
    public static final String PARAM_EDIT_ID = "edit_id";
    @SpringBean(name = "flightService")
    private FlightService mFlightService;
    @SpringBean(name = "destinationService")
    private DestinationService mDestService;
    @SpringBean(name = "stewardService")
    private StewardService mStewardService;
    @SpringBean(name = "aircraftService")
    private AircraftService mPlaneService;

    public FlightsView(final PageParameters parameters)
    {
        super(parameters);

        StringValue deleteId = parameters.get(PARAM_DELETE_ID);
        if (deleteId != null && !deleteId.isEmpty())
            mFlightService.remove(mFlightService.get(deleteId.toLongObject()));

        StringValue editId = parameters.get(PARAM_EDIT_ID);
        final FlightDTO editFlight =
                editId != null && !editId.isEmpty() ? mFlightService.get(editId.toLongObject()) : null;

        HandleForm(parameters, editFlight);

        HandleData(parameters);
        
        Component show = new AbstractLink("showForm") {};
        add(show);
        MetaDataRoleAuthorizationStrategy.authorize(show, RENDER, HeathrowRoles.ADMIN);
        
        Label info = new Label("info", new StringResourceModel("info", this, null));
        add(info);
        info.setVisible(SecureWicketAuthenticatedWebSession.get().getRoles().equals(new Roles()));
        
        Component header = new AbstractItem("header");
        add(header);
        MetaDataRoleAuthorizationStrategy.authorize(header, RENDER, HeathrowRoles.USER);
    }

    private void HandleData(final PageParameters parameters)
    {
        RepeatingView flightsView = new RepeatingView("flights");
        MetaDataRoleAuthorizationStrategy.authorize(flightsView, RENDER, HeathrowRoles.USER);
        add(flightsView);
        
        Label connectionError = new Label("error", new StringResourceModel("error", this, null));
        add(connectionError);
        connectionError.setVisible(false);
        
        try
        {
            for (FlightDTO fl : mFlightService.findAll())
            {
                AbstractItem item = new AbstractItem(flightsView.newChildId());

                item.add(new Label("flight_id", String.valueOf(fl.getId())));
                item.add(new Label("flight_from", fl.getFlightFrom().getCity() + " (" + fl.getFlightFrom().getStateCode() + ")"));
                item.add(new Label("flight_to", fl.getFlightTo().getCity() + " (" + fl.getFlightTo().getStateCode() + ")"));
                item.add(new Label("flight_plane", fl.getAircraft().getCode()));
                item.add(new Label("flight_depart", Utils.FormatDateTime(fl.getDeparture())));
                item.add(new Label("flight_arri", Utils.FormatDateTime(fl.getArrival())));
                item.add(new Label("stew_count", String.valueOf(fl.getStewards().size())));

                PageParameters deleteParams = new PageParameters();
                deleteParams.add(PARAM_DELETE_ID, fl.getId().toString());
                BookmarkablePageLink delete = new BookmarkablePageLink("delete_flight", FlightsView.class, deleteParams);
                MetaDataRoleAuthorizationStrategy.authorize(delete, RENDER, HeathrowRoles.ADMIN);
                item.add(delete);

                PageParameters editParams = new PageParameters();
                editParams.add(PARAM_EDIT_ID, fl.getId().toString());
                BookmarkablePageLink edit = new BookmarkablePageLink("edit_flight", FlightsView.class, editParams);
                MetaDataRoleAuthorizationStrategy.authorize(edit, RENDER, HeathrowRoles.ADMIN);
                item.add(edit);
                
                flightsView.add(item);
            }
        } catch (Exception ex)
        {
            Logger.getLogger(FlightsView.class.getName()).log(Level.SEVERE, null, ex);
            connectionError.setVisible(!SecureWicketAuthenticatedWebSession.get().getRoles().equals(new Roles()));
        }
    }

    private void HandleForm(final PageParameters parameters, final FlightDTO editFlight)
    {
        Form fo = new Form("flightForm");
        add(fo);
        fo.add(new Label("heading", new StringResourceModel(editFlight == null ? "form.addHeading" : "form.editHeading", this, null)));

        final TextField<Long> flightId =
                new TextField<Long>("flight_id",
                new Model<Long>(editFlight != null ? editFlight.getId() : null));
        fo.add(flightId);

        final TextField<String> flightFrom =
                new TextField<String>("flight_from_inp",
                new Model<String>(Utils.FormatDate(editFlight != null ? editFlight.getArrival() : Calendar.getInstance())));
        flightFrom.setRequired(true);
        fo.add(flightFrom);

        final TextField<String> flightFromT =
                new TextField<String>("flight_from_inp_t",
                new Model<String>(editFlight != null ? Utils.FormatTime(editFlight.getArrival()) : "10:00"));
        flightFromT.setRequired(true);
        fo.add(flightFromT);

        final TextField<String> flightTo =
                new TextField<String>("flight_to_inp",
                new Model<String>(Utils.FormatDate(editFlight != null ? editFlight.getDeparture() : Calendar.getInstance())));
        flightTo.setRequired(true);
        fo.add(flightTo);

        final TextField<String> flightToT =
                new TextField<String>("flight_to_inp_t",
                new Model<String>(editFlight != null ? Utils.FormatTime(editFlight.getDeparture()) : "20:00"));
        flightToT.setRequired(true);
        fo.add(flightToT);

        final TextField<String> aircraftInp =
                new TextField<String>("aircraft_inp",
                new Model<String>(editFlight != null ? editFlight.getAircraft().getCode() : null));
        aircraftInp.setRequired(true);
        fo.add(aircraftInp);
        final TextField<Long> aircraftInpId =
                new TextField<Long>("aircraft_inp_id",
                new Model<Long>(editFlight != null ? editFlight.getAircraft().getId() : null));
        aircraftInpId.setRequired(true);
        fo.add(aircraftInpId);

        final TextField<String> destFrom =
                new TextField<String>("destFrom_inp",
                new Model<String>(editFlight != null ? editFlight.getFlightFrom().getCity() : null));
        destFrom.setRequired(true);
        fo.add(destFrom);
        final TextField<Long> destFromId =
                new TextField<Long>("destFrom_inp_id",
                new Model<Long>(editFlight != null ? editFlight.getFlightFrom().getId() : null));
        destFromId.setRequired(true);
        fo.add(destFromId);

        final TextField<String> destTo =
                new TextField<String>("destTo_inp",
                new Model<String>(editFlight != null ? editFlight.getFlightFrom().getCity() : null));
        destTo.setRequired(true);
        fo.add(destTo);
        final TextField<Long> destToId =
                new TextField<Long>("destTo_inp_id",
                new Model<Long>(editFlight != null ? editFlight.getFlightTo().getId() : null));
        destToId.setRequired(true);
        fo.add(destToId);


        final TextField<String> stewardInp =
                new TextField<String>("steward_inp",
                new Model<String>(""));
        fo.add(stewardInp);

        StringBuilder stewardsIdsStr = null;
        if (editFlight != null)
        {
            stewardsIdsStr = new StringBuilder();
            if (editFlight.getStewards() != null)
                for (StewardDTO stew : editFlight.getStewards())
                    stewardsIdsStr.append(stew.getId() + ";");
        }

        final TextField<String> stewardIds =
                new TextField<String>("steward_inp_id",
                new Model<String>(stewardsIdsStr == null ? null : stewardsIdsStr.toString()));
        fo.add(stewardIds);

        Button buttonOk = new Button("buttonOk")
        {
            @Override
            public void onSubmit()
            {
                try
                {
                    FlightDTO fl;
                    if (editFlight == null)
                        fl = new FlightDTO();
                    else
                        fl = editFlight;

                    fl.setAircraft(mPlaneService.get(Long.valueOf(aircraftInpId.getValue())));

                    fl.setFlightFrom(mDestService.getDestination(Long.valueOf(destFromId.getValue())));

                    fl.setFlightTo(mDestService.getDestination(Long.valueOf(destToId.getValue())));

                    HashSet<Long> stewIds = new HashSet<Long>();
                    for (String id : stewardIds.getValue().split(";"))
                    {
                        if (!id.isEmpty())
                            stewIds.add(Long.valueOf(id));
                    }

                    fl.setStewards(new ArrayList<StewardDTO>());
                    for (Long stewId : stewIds)
                        fl.getStewards().add(mStewardService.get(stewId));

                    fl.setDeparture(new GregorianCalendar());
                    Utils.parseDate(flightFrom.getValue(), flightFromT.getValue(), fl.getDeparture());

                    fl.setArrival(new GregorianCalendar());
                    Utils.parseDate(flightTo.getValue(), flightToT.getValue(), fl.getArrival());

                    if (fl.getId() == null)
                        mFlightService.create(fl);
                    else
                        mFlightService.update(fl);
                } catch (ParseException ex)
                {
                    Logger.getLogger(FlightsView.class.getName()).log(Level.SEVERE, null, ex);
                } catch (Exception ex)
                {
                    Logger.getLogger(FlightsView.class.getName()).log(Level.SEVERE, null, ex);
                }

                setResponsePage(FlightsView.class);
            }
        };
        Button buttonCancel = new Button("buttonCancel")
        {
            @Override
            public void onSubmit()
            {
                setResponsePage(FlightsView.class);
            }
        };

        fo.add(buttonOk);
        fo.add(buttonCancel);

    }
}
